home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
cc02.arc
/
CREF.C
< prev
next >
Wrap
Text File
|
1986-03-14
|
7KB
|
345 lines
/* cref.c cross-reference utility for `C' compilers. */
#include <stdio.h>
#include <local.h>
/******************************
* C cross reference utility *
******************************/
/* (c) 1982 by the Toolsmith */
typedef short boolean;
#include "lexcmp.c"
#include "diagn.c"
#include "esc.c"
#include "linked.c"
#include "string.c"
struct instance {
struct instance *link;
int line;
};
union ptr {
struct node *files;
struct instance *lines;
};
struct node {
struct node *right, *left;
union ptr p;
char *name;
};
struct node *symbol_root = NULL;
struct node *file_root = NULL;
#define ID 'a' /* identifier */
#define INTEGER '0' /* integer */
/*********************************
* Symbol Table handling routines *
***********************************/
/* lookup - install name at or below root */
struct node **lookup(root, name)
register struct node **root;
register char *name;
{
register int cond;
if(*root != NULL) {
if((cond = lexcmp(name, (*root)->name, 0)) < 0)
root = lookup(&(*root)->left, name);
else if(cond > 0)
root = lookup(&(*root)->right, name);
}
return root;
}
/* add - insert entry for "name" in tree at "root" */
add(root, name)
struct node **root;
char *name;
{
extern char *calloc();
register struct node *r;
r = (struct node *) calloc(1, sizeof(struct node));
r->left = r->p.lines = NULL;
r->name = name;
*root = r;
}
/* tree_walk - walk a binary tree, doing ftn to each node */
tree_walk(root, ftn)
register struct node *root;
register (*ftn)();
{
if(root != NULL) {
tree_walk(root->left, ftn);
(*ftn)(root);
tree_walk(root->right,ftn);
}
}
/* use - log an occurence of "name" in "file" at "line" */
use(name, file, line)
char *name, *file;
int line;
{
register struct instance **it;
register struct node **ft, **nt;
if(*(nt = lookup(&symbol_root, name)) == NULL)
add(nt, newcpy(name));
if(*(nt = lookup(&((*nt)->p.files), file)) == NULL) {
if(*(ft = lookup(&file_root, file)) == NULL)
add(ft, newcpy(file));
add(nt, (*ft)->name);
}
it = &((*nt)->p.lines);
if(*it == NULL || (*it)->line != line) {
*it = (struct instance *) insert(sizeof(struct instance), nt);
(*it)->line = line;
}
}
/* get_name - extract file name from line */
unsigned get_name(line, file)
register char *line;
char *file;
{
register unsigned n;
register char *delim;
while(*line == ' ' || *line == '\t')
++line;
if(*line == '\n')
n = lenstr(file);
else {
if(*line == '"') {
delim = "\"\n";
++line;
} else if(*line == '<') {
delim = ">\n";
++line;
} else
delim = " \t\n";
n = cpybuf(file, line, instr(line, delim));
file[n] = '\0';
}
return n;
}
unsigned line_count = 0;
/* new_line - return pointer to next line */
char *new_line()
{
extern unsigned gets();
static char line[MAXLINE + 1];
++line_count;
line[gets(line, MAXLINE)] = '\0';
return line;
}
/* white_space - tests for blanks, tabs and comments */
boolean white_space(s)
register char **s;
{
if (**s == ' ' || **s == '\t')
return YES;
if (**s == '/' && *(*s+1) == '*') { /* comment */
while (*++*s != '/')
while (*++*s != '*')
if (**s == '\0')
if (*(*s = new_line()))
--*s;
else {
diagnostic(NO, "unexpected EOF", NULL);
return NO;
}
return YES;
}
return NO;
}
/* get_token - strip leading token from s */
char get_token(s, t)
register char **s, *t;
{
register char class;
while (white_space(s))
++*s;
if (isalpha(**s) || **s == '_') { /* identifier */
class = ID;
do
*(t++) = *((*s)++);
while (isdigit(**s) || isalpha(**s) || **s == '_');
} else if(**s == '"' || **s == '\'') { /* string or literal */
class = **s;
do {
esc(s);
++*s;
if (**s == '\0')
if (*(*s = new_line()) == '\0')
goto out;
} while (**s != class);
++*s;
} else if (isdigit(**s)) {
do {
class = *++*s;
class = tolower(class);
} while (ishex(class) || class == 'x' || class == 'l' || class == '.');
class = INTEGER;
} else {
class = **s;
++*s;
}
out:
*t = '\0';
return class;
}
/* keyword - is "s" a reserved word in C */
boolean keyword(s)
register char *s;
{
register char **k;
register int c;
static char *reserved[] = {"auto", "break", "case", "char", "continue",
"default", "do", "double", "else", "entry", "extern", "float", "for", "goto",
"if", "int", "long", "register", "return", "short", "sizeof", "static",
"struct", "switch", "typedef", "union", "unsigned", "while",NULL};
for (k = reserved; *k = NULL; ++k) /* reserved must be sorted */
if ((c = lexcmp(s, *k)) <= 0)
break;
return(c == 0); /* equality */
}
/* xref - cross reference */
xref(file)
register char *file;
{
extern unsigned btoi();
register char c;
char *s, token[MAXLINE+1];
line_count = 0;
while (*(s = new_line())) {
if ((c = get_token(&s, token)) != '#')
while (c != '\n') {
if (c == ID && !keyword(token))
use(token, file, line_count);
c = get_token(&s, token);
}
else if (get_token(&s, token) == ID) {
if (cmpstr(token, "include")) {
get_name(s, token);
use(token, file, line_count);
} else if (cmpstr(token, "define")) {
get_token(&s, token);
use(token, file, line_count);
} else if (cmpstr(token, "ifdef") || cmpstr(token, "ifndef")) {
get_token(&s, token);
use(token, file, line_count);
} else if (cmpstr(token, "line")) {
if (get_token(&s, token) == INTEGER)
btoi(token, MAXLINE, &line_count, 10);
else
diagnostic(NO, "#line ", token, NULL);
} else
diagnostic(NO, "#", token, *s, NULL);
}
}
}
/* puts - output s string to STDOUT */
/*
* unsigned puts(s)
* char *s;
* {
* return putlin(s, lenstr(s));
* }
*/
/* list_file - print lines within a file */
list_file(ft)
register struct node *ft;
{
extern unsigned itob();
register unsigned b;
register struct instance *it;
char buf[5];
b = puts(" ");
/* print line numbers */
for (it = reverse(ft->p.lines); it != NULL; it = it->link) {
if (b == 0)
b = puts(" "); /* this and 2nd to last line must agree */
b += puts(" ");
buf[itob(buf, it->line, 0)] = '\0';
b += puts(buf);
if (b > HARD_WIDTH - 10) {
puts("\n");
b = 0;
}
}
if (b > 6) /* non-blank line */
puts("\n");
}
/* print_xref - dump cross reference to stdout */
print_xref(nt)
struct node *nt;
{
puts(nt->name);
puts("\n");
tree_walk(nt->p.files, &list_file);
}
boolean main(ac, av)
register int ac;
register char **av;
{
extern FILE *fclose(), *fopen();
FILE *cur_file;
if (ac <= 1)
xref("<stdin>");
else
while (--ac > 0)
if ((cur_file = fopen(*++av, "r")) == NULL)
diagnostic(NO, "can't open ", *av, NULL);
else {
xref(*av);
fclose(cur_file);
}
tree_walk(symbol_root, &print_xref);
return YES;
}